package at.fhooe.mc;

import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Test;
import at.fhooe.mc.control.ElevatorControlCenter;
import at.fhooe.mc.control.IAdapter;
import at.fhooe.mc.data.ControlMode;
import at.fhooe.mc.data.DirectionType;
import at.fhooe.mc.data.control.ElevatorControlData;
import at.fhooe.mc.model.ElevatorControlCenterObserver;

public class ElevatorControlCenterTest
{
	private ElevatorControlCenter ecc;
	private IAdapter mock;
	private IMocksControl ctrl;

	private ElevatorControlCenterObserver mockObserver;

	@Before
	public void setUp()
	{
		ctrl = EasyMock.createStrictControl();
		mock = ctrl.createMock(IAdapter.class);

		mockObserver = ctrl.createMock(ElevatorControlCenterObserver.class);

		ecc = new ElevatorControlCenter();
		ecc.setAdapter(mock);
	}

	@Test
	public void testNoAdapterSet() throws Exception
	{

		try
		{
			ElevatorControlCenter eccTest = new ElevatorControlCenter();
			eccTest.init();
			fail("NullPointerException expected");
		}
		catch (NullPointerException e)
		{
			// do nothing
		}
	}

	@Test
	public void testInit() throws Exception
	{
		expect(mock.init()).andReturn(true);

		ctrl.replay();

		assertTrue(ecc.init());

		ctrl.verify();
	}

	@Test
	public void testInitFailed() throws Exception
	{
		expect(mock.init()).andReturn(false);

		ctrl.replay();

		assertFalse(ecc.init());

		ctrl.verify();
	}

	@Test
	public void testAutoControl() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.AUTOMATIC);

		ecc.getControlElevatorData().add(data);

		ecc.autoControl(0, 4);

		assertEquals(4,ecc.getControlElevatorData().get(0).getNewTarget());
		assertEquals(ControlMode.AUTOMATIC, ecc.getControlElevatorData().get(0).getMode());
	}

	@Test
	public void testAutoControlInManualMode() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);
		data.setNewTarget(2);

		ecc.getControlElevatorData().add(data);

		ecc.autoControl(0, 4);

		assertEquals(2,ecc.getControlElevatorData().get(0).getNewTarget());
		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(0).getMode());
	}

	@Test
	public void testAutoControlMultipleElevators() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.AUTOMATIC);
		data.setNewTarget(1);

		ecc.getControlElevatorData().add(data);

		data = new ElevatorControlData();
		data.setMode(ControlMode.AUTOMATIC);
		data.setNewTarget(2);

		ecc.getControlElevatorData().add(data);

		data = new ElevatorControlData();
		data.setMode(ControlMode.AUTOMATIC);
		data.setNewTarget(3);

		ecc.getControlElevatorData().add(data);

		ecc.autoControl(1, 4);

		assertEquals(1,ecc.getControlElevatorData().get(0).getNewTarget());
		assertEquals(4,ecc.getControlElevatorData().get(1).getNewTarget());
		assertEquals(3,ecc.getControlElevatorData().get(2).getNewTarget());

		assertEquals(ControlMode.AUTOMATIC, ecc.getControlElevatorData().get(0).getMode());
		assertEquals(ControlMode.AUTOMATIC, ecc.getControlElevatorData().get(1).getMode());
		assertEquals(ControlMode.AUTOMATIC, ecc.getControlElevatorData().get(2).getMode());
	}

	@Test
	public void testManualControl() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);

		ecc.getControlElevatorData().add(data);

		ecc.manualControl(0, 4);

		assertEquals(4,ecc.getControlElevatorData().get(0).getNewTarget());
		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(0).getMode());
	}

	@Test
	public void testManualControlInAutomaticMode() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.AUTOMATIC);
		data.setNewTarget(2);

		ecc.getControlElevatorData().add(data);

		ecc.manualControl(0, 4);

		assertEquals(2,ecc.getControlElevatorData().get(0).getNewTarget());
		assertEquals(ControlMode.AUTOMATIC, ecc.getControlElevatorData().get(0).getMode());
	}

	@Test
	public void testManualControlMultipleElevators() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);
		data.setNewTarget(1);

		ecc.getControlElevatorData().add(data);

		data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);
		data.setNewTarget(2);

		ecc.getControlElevatorData().add(data);

		data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);
		data.setNewTarget(3);

		ecc.getControlElevatorData().add(data);

		ecc.manualControl(1, 4);

		assertEquals(1,ecc.getControlElevatorData().get(0).getNewTarget());
		assertEquals(4,ecc.getControlElevatorData().get(1).getNewTarget());
		assertEquals(3,ecc.getControlElevatorData().get(2).getNewTarget());

		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(0).getMode());
		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(1).getMode());
		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(2).getMode());
	}

	@Test
	public void testManualDirection() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);

		ecc.getControlElevatorData().add(data);

		ecc.manualDirection(0, DirectionType.UNCOMMITTED);

		assertEquals(DirectionType.UNCOMMITTED,ecc.getControlElevatorData().get(0).getNewDirection());
		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(0).getMode());
	}

	@Test
	public void testManualDirectionAutomaticMode() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.AUTOMATIC);
		data.setNewDirection(DirectionType.UP);

		ecc.getControlElevatorData().add(data);

		ecc.manualDirection(0, DirectionType.UNCOMMITTED);

		assertEquals(DirectionType.UP,ecc.getControlElevatorData().get(0).getNewDirection());
		assertEquals(ControlMode.AUTOMATIC, ecc.getControlElevatorData().get(0).getMode());
	}

	@Test
	public void testManualDirectionMultipleElevators() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);
		data.setNewDirection(DirectionType.UP);

		ecc.getControlElevatorData().add(data);

		data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);
		data.setNewDirection(DirectionType.DOWN);

		ecc.getControlElevatorData().add(data);

		data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);
		data.setNewDirection(DirectionType.UNCOMMITTED);

		ecc.getControlElevatorData().add(data);

		ecc.manualDirection(1, DirectionType.UNCOMMITTED);

		assertEquals(DirectionType.UP,ecc.getControlElevatorData().get(0).getNewDirection());
		assertEquals(DirectionType.UNCOMMITTED,ecc.getControlElevatorData().get(1).getNewDirection());
		assertEquals(DirectionType.UNCOMMITTED,ecc.getControlElevatorData().get(2).getNewDirection());

		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(0).getMode());
		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(1).getMode());
		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(2).getMode());
	}

	@Test
	public void testChangeControlMode() throws Exception
	{
		ElevatorControlData data = new ElevatorControlData();
		data.setMode(ControlMode.MANUAL);

		ecc.getControlElevatorData().add(data);

		ecc.changeControlMode(0, ControlMode.AUTOMATIC);

		assertEquals(-1,ecc.getControlElevatorData().get(0).getNewTarget());
		assertEquals(ControlMode.AUTOMATIC, ecc.getControlElevatorData().get(0).getMode());

		ecc.changeControlMode(0, ControlMode.MANUAL);

		assertEquals(-1,ecc.getControlElevatorData().get(0).getNewTarget());
		assertEquals(ControlMode.MANUAL, ecc.getControlElevatorData().get(0).getMode());
	}

	@Test
	public void testNotifyObservers() throws Exception
	{
		mockObserver.updateNewValues(null);

		ecc.registerObserver(mockObserver);

		ctrl.replay();

		ecc.notifyObservers();

		ctrl.verify();
	}

	@Test
	public void testUnregisterObserver() throws Exception
	{
		ecc.registerObserver(mockObserver);
		ecc.unregisterObserver(mockObserver);

		ctrl.replay();

		ecc.notifyObservers();

		ctrl.verify();
	}
}
